package com.cms.kernel.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

/**
 * Copyright (C) 2013 2016 Well
 * 文件:RequestUtil.java
 * 创建:Well
 * 日期:2016年5月25日 下午3:09:10
 * 来自:
 * 版本:1.0.0
 * 描述:请求的util类，处理前台发送过来的请求
 *      对于获取前台请求参数的值，也可以在请求的方法中通过对参数利用注解的方式来实现
 *      例：
 *          在controller中
 *          public void getString(@RequestParam(value="paramName")String paramValue)
 *          {
 *              // paramValue就是前台参数paramName的值
 *          }
 */

public class RequestUtil
{
	private static Logger logger = LogManager.getLogger(RequestUtil.class);

	/**
	 * 获取前台请求的字符串值
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @return 前台请求参数的字符串值
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回null
	 */
	public static String getString(HttpServletRequest request, String name)
	{
		return request.getParameter(name);
	}

	/**
	 * 获取前台请求的字符串值
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @param defaultValue 默认值
	 * @return 前台请求参数的字符串值
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回默认值
	 */
	public static String getString(HttpServletRequest request, String name, String defaultValue)
	{
		String value = getString(request, name);
		return value == null ? defaultValue : value;
	}

	/**
	 * 获取前台请求的字符串数组
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @return 前台请求参数的字符串数组
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回null
	 */
	public static String[] getStrings(HttpServletRequest request, String name)
	{
		return request.getParameterValues(name);
	}

	/**
	 * 获取前台请求的字符串链表
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @return 前台请求参数的字符串链表
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回null
	 */
	public static List<String> getStringList(HttpServletRequest request, String name)
	{
		List<String> stringList = null;
		String[] strings=getStrings(request, name);
		if(null!=strings)
		{
			stringList=Arrays.asList(strings);
		}
		return stringList;
	}

	/**
	 * 获取前台请求的整型值
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @return 前台请求参数的整型值
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回null
	 */
	public static Integer getInteger(HttpServletRequest request, String name)
	{
		Integer value = null;
		String s = getString(request, name);
		if (null != s)
		{
			value = Integer.valueOf(s);
		}
		return value;
	}

	/**
	 * 获取前台请求的整型值
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @param defaultValue 默认值
	 * @return 前台请求参数的整型值
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回默认值
	 */
	public static Integer getInteger(HttpServletRequest request, String name, Integer defaultValue)
	{
		Integer value = getInteger(request, name);
		return value == null ? defaultValue : value;
	}

	/**
	 * 获取前台请求的整型数组
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @return 前台请求参数的整型数组
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回null
	 */
	public static Integer[] getIntegers(HttpServletRequest request, String name)
	{
		Integer[] values = null;
		String[] strings=getStrings(request,name);
		if (null != strings)
		{
			int length = strings.length;
			if (length > 0)
			{
				values = new Integer[length];
				for (int i = 0; i < length; i++)
				{
					values[i] = Integer.valueOf(strings[i]);
				}
			}
		}
		return values;
	}

	/**
	 * 获取前台请求的整型链表
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @return 前台请求参数的整型链表
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回null
	 */
	public static List<Integer> getIntegerList(HttpServletRequest request, String name)
	{
		List<Integer> integerList = null;
		Integer[] integers=getIntegers(request,name);
		if(null!=integers)
		{
			integerList = Arrays.asList(integers);
		}
		return integerList;
	}

	/**
	 * 获取前台请求的长整型值
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @return 前台请求参数的长整型值
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回null
	 */
	public static Long getLong(HttpServletRequest request, String name)
	{
		Long value = null;
		String s = getString(request, name);
		if (null != s)
		{
			value = Long.valueOf(s);
		}
		return value;
	}

	/**
	 * 获取前台请求的长整型值
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @param defaultValue 默认值
	 * @return 前台请求参数的长整型值
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回默认值
	 */
	public static Long getLong(HttpServletRequest request, String name, Long defaultValue)
	{
		Long value = getLong(request, name);
		return value == null ? defaultValue : value;
	}

	/**
	 * 获取前台请求的长整型数组
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @return 前台请求参数的长整型数组
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回null
	 */
	public static Long[] getLongs(HttpServletRequest request, String name)
	{
		Long[] values = null;
		String[] stringArray = request.getParameterValues(name);
		if (null != stringArray)
		{
			int length = stringArray.length;
			if (length > 0)
			{
				values = new Long[length];
				for (int i = 0; i < length; i++)
				{
					values[i] = Long.valueOf(stringArray[i]);
				}
			}
		}
		return values;
	}

	/**
	 * 获取前台请求的长整型链表
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @return 前台请求参数的长整型链表
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回null
	 */
	public static List<Long> getLongList(HttpServletRequest request, String name)
	{
		List<Long> longList = null;
		Long[] longs=getLongs(request,name);
		if(null!=longs)
		{
			longList = Arrays.asList(longs);
		}
		return longList;
	}

	/**
	 * 获取前台请求的双精度值
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @return 前台请求参数的双精度值
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回null
	 */
	public static Double getDouble(HttpServletRequest request, String name)
	{
		Double value = null;
		String s = getString(request, name);
		if (null != s)
		{
			value = Double.valueOf(s);
		}
		return value;
	}

	/**
	 * 获取前台请求的双精度值
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @param defaultValue 默认值
	 * @return 前台请求参数的双经度值
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回默认值
	 */
	public static Double getDouble(HttpServletRequest request, String name, Double defaultValue)
	{
		Double value = getDouble(request, name);
		return value == null ? defaultValue : value;
	}

	/**
	 * 获取前台请求的双精度数组
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @return 前台请求参数的双精度数组
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回null
	 */
	public static Double[] getDoubles(HttpServletRequest request, String name)
	{
		Double[] values = null;
		String[] strings=getStrings(request,name);
		if (null != strings)
		{
			int length = strings.length;
			if (length > 0)
			{
				values = new Double[length];
				for (int i = 0; i < length; i++)
				{
					values[i] = Double.valueOf(strings[i]);
				}
			}
		}
		return values;
	}

	/**
	 * 获取前台请求的双精度链表
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @return 前台请求参数的双精度链表
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回null
	 */
	public static List<Double> getDoubleList(HttpServletRequest request, String name)
	{
		List<Double> doubleList = null;
		Double[] doubles=getDoubles(request,name);
		if(null!=doubles)
		{
			doubleList = Arrays.asList(doubles);
		}
		return doubleList;
	}

	/**
	 * 获取前台请求的浮点数值
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @return 前台请求参数的浮点数值
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回null
	 */
	public static Float getFloat(HttpServletRequest request, String name)
	{
		Float value = null;
		String s = getString(request, name);
		if (null != s)
		{
			value = Float.valueOf(s);
		}
		return value;
	}

	/**
	 * 获取前台请求的浮点数值
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @param defaultValue 默认值
	 * @return 前台请求参数的浮点数值
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回默认值
	 */
	public static Float getFloat(HttpServletRequest request, String name, Float defaultValue)
	{
		Float value = getFloat(request, name);
		return value == null ? defaultValue : value;
	}

	/**
	 * 获取前台请求的浮点数数组
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @return 前台请求参数的浮点数数组
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回null
	 */
	public static Float[] getFloats(HttpServletRequest request, String name)
	{
		Float[] values = null;
		String[] strings = getStrings(request, name);
		if (null != strings)
		{
			int length = strings.length;
			if (length > 0)
			{
				values = new Float[length];
				for (int i = 0; i < length; i++)
				{
					values[i] = Float.valueOf(strings[i]);
				}
			}
		}
		return values;
	}

	/**
	 * 获取前台请求的浮点数链表
	 * @param request 请求
	 * @param name 前台请求的参数名称
	 * @return 前台请求参数的浮点熟链表
	 * 		        如果name不正确或者与前台请求的参数名称不匹配，则返回null
	 */
	public static List<Float> getFloatList(HttpServletRequest request, String name)
	{
		List<Float> floatList = null;
		Float[] floats=getFloats(request,name);
		if(null!=floats)
		{
			floatList = Arrays.asList(floats);
		}
		return floatList;
	}

	/**
	 * 获取前台请求的大整型值
	 * @param request 请求
	 * @param name 参数名称
	 * @return 大数，整型值
	 * 		   name不正确 或者与前台请求的参数不匹配，返回null
	 */
	public static BigInteger getBigInteger(HttpServletRequest request,String name)
	{
		BigInteger bigInteger=null;
		String s=getString(request,name);
		if(StringUtils.isNotBlank(s))
		{
			bigInteger=new BigInteger(s);
		}
		return bigInteger;
	}
	
	/**
	 * 获取前台请求的大数值
	 * @param request 请求
	 * @param name 参数名称
	 * @return 大数
	 * 	       name不正确或者与前台请求的参数不匹配，返回null
	 */
	public static BigDecimal getBigDecimal(HttpServletRequest request,String name)
	{
		BigDecimal bigDecimal=null;
		String s=getString(request,name);
		if(StringUtils.isNotBlank(s))
		{
			bigDecimal=new BigDecimal(s);
		}
		return bigDecimal;
	}
	
	/**
	 * 获取中文字符串
	 * 主要是解决get请求的时候，前台传递中文，后台获取时出现乱码；
	 * @param request 请求
	 * @param name 前台参数的名称
	 * @return 前台请求的中文字符串
	 * 		        出现异常返回null
	 */
	public static String getChinese(HttpServletRequest request, String name)
	{
		String value = null;
		String s=getString(request,name);
		try
		{
			if (null != s)
			{
				String method=request.getMethod(); // 请求的方法
				if(StringUtils.equalsIgnoreCase(method, "GET")) // get方法
				{
					value = new String(s.getBytes("ISO8859-1"), "UTF-8");
				}
				else if(StringUtils.equalsIgnoreCase(method, "POST")) // post方法
				{
					value=s;
				}
				else
				{
					value=null;
					logger.warn("非法的请求方法，确保请求方法是get或者post");
				}
			}
		}
		catch (UnsupportedEncodingException e)
		{
			logger.error(e);
		}
		
		return value;
	}

	/**
	 * 获取请求的IP地址
	 * 经过下面一系列的代理，IP地址会发生改变
	 *  X-Forwarded-For,Proxy-Client-IP,WL-Proxy-Client-IP,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FOR
	 * @param request
	 * @return 前台请求的IP地址
	 * 		        出现异常返回null
	 */
	public static String getIP(HttpServletRequest request)
	{
		String ip = null;
		try
		{
			String[] proxys =
			{ "X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR" };
			for (String proxy : proxys)
			{
				ip = request.getHeader(proxy);
				if (StringUtils.isBlank(ip) || "unkown".equalsIgnoreCase(ip))
				{
					continue;
				}
				else
				{
					break;
				}
			}
			if (StringUtils.isBlank(ip) || "unkown".equalsIgnoreCase(ip))
			{
				ip = request.getRemoteAddr();
				if ("127.0.0.1".equals(ip))
				{
					InetAddress inetAddress = InetAddress.getLocalHost();
					ip = inetAddress.getHostAddress();
				}
			}
			if (null != ip && ip.length() > 15)
			{
				int index = ip.indexOf(",");
				if (index > 0)
				{
					ip = ip.substring(0, index);
				}
			}
		}
		catch (Exception e)
		{
			logger.error(e);
		}
		return ip;
	}
	
	/**
	 * 分页时，获取当前的页码
	 * 规定前台请求的页码的参数为page
	 * @param request 请求
	 * @return 当前分页的页码
	 * 		        出现异常或者前台参数不是page，返回null
	 */
	public static Integer getPage(HttpServletRequest request)
	{
		return getInteger(request, "page");
	}

	/**
	 * 分页时，获取当前的页码
	 * 规定前台请求的页码的参数为page
	 * @param request 请求
	 * @param page 默认页码
	 * @return 当前分页的页码
	 *         出现异常或者前台参数不是page，返回默认页码
	 */
	public static Integer getPage(HttpServletRequest request, Integer page)
	{
		return getInteger(request, "page", page);
	}

	/**
	 * 分页时，获取一页的行数
	 * 规定前台请求行数的参数必须是rows
	 * @param request 请求
	 * @return 当前一页的行数
	 *         出现异常或者前台参数不是rows，返回null
	 */
	public static Integer getRows(HttpServletRequest request)
	{
		return getInteger(request, "rows");
	}

	/**
	 * 分页时，获取一页的行数
	 * 规定前台请求行数的参数必须是rows
	 * @param request 请求
	 * @param rows 默认行数
	 * @return 当前一页的行数
	 * 	                   出现异常或者前台参数不是rows，返回null
	 */
	public static Integer getRows(HttpServletRequest request, Integer rows)
	{
		return getInteger(request, "rows", rows);
	}

	/**
	 * 获取项目的绝对根路径
	 * 	在eclipse的项目中，默认的绝对根路径是WebContent文件夹的绝对路径
	 * 	在idea的项目中，默认的绝对根路径是web文件夹的绝对路径
	 * @param request 请求
	 * @return 项目的绝对跟路径，即项目在服务器上的绝对路径
	 */
	public static String getRealPath(HttpServletRequest request)
	{
		return getRealPath(request,"/");
	}

	/**
	 * 获取项目绝对根路径下文件夹的绝对路径
	 * @param request 请求
	 * @param path 文件夹的相对路径，相对于项目跟路径
	 * @return 指定文件夹的绝对路径
	 * 		例：在eclipse的项目中，在WebContent文件夹下面有一个asset文件夹，asset下面有一个js文件夹
	 * 			如果想要获取js文件夹在服务器上的绝对路径，path就应该是 "asset"+File.separator+"js"+File.separator
	 * 		注:File.separator是跨平台的文件路径符
	 */
	public static String getRealPath(HttpServletRequest request,String path)
	{	
		return request.getSession().getServletContext().getRealPath(path);
	}
	
	/**
	 * 获取请求的session的id
	 * @param request 请求
	 * @return session的id
	 */
	public static String getSessionID(HttpServletRequest request)
	{
		return request.getSession().getId();
	}
	
	/**
	 * 判断请求是否为AJAX请求
	 * @param request
	 * @return
	 *      true---AJAX请求
	 *      false---非AJAX请求
	 */
	public static boolean isAJAXRequest(HttpServletRequest request)
	{
		String header=request.getHeader("x-requested-with");
		if(null!=header && StringUtils.equalsIgnoreCase(header, "XMLHttpRequest"))
		{
			return true;
		}
		return false;
	}

	/******************************************************************************************************************/

	/**
	 * 获取请求的头部信息
	 * @param request
	 */
	public static void getHeaderInfo(HttpServletRequest request)
	{
		Enumeration<String> headerNames = request.getHeaderNames();
		while (headerNames.hasMoreElements())
		{
			String headerName = headerNames.nextElement();
			logger.info("headerName：" + headerName);
		}
	}

	/**
	 * 获取参数信息
	 * @param request
	 */
	public static void getParameterInfo(HttpServletRequest request)
	{
		Map<String, String[]> parameterMap = request.getParameterMap();
		for (int i = 0; i < parameterMap.size(); i++)
		{
			String[] parameters = parameterMap.get(i);
			if (null != parameters)
			{
				for (String parameter : parameters)
				{
					logger.info(parameter + ",");
				}
				logger.info("");
			}
		}

		Enumeration<String> parameterNames = request.getParameterNames();
		while (parameterNames.hasMoreElements())
		{
			String parameterName = parameterNames.nextElement();
			logger.info("parameterName：" + parameterName);
		}
	}

	/**
	 * 获取路径信息
	 * @param request
	 */
	public static void getPathInfo(HttpServletRequest request)
	{
		request.getPathInfo();
		request.getContextPath();
		request.getPathTranslated();
		request.getServletPath();
		request.getServletContext();
		request.getServletContext().getRealPath("/");
		request.getServletContext().getRealPath("");
		request.getServletContext().getContextPath();
		request.getSession().getServletContext().getRealPath("/");
		request.getSession().getServletContext().getRealPath("");
		request.getSession().getServletContext().getContextPath();
		request.getServletContext().getRealPath(request.getRequestURI());
	}

	/**
	 * 获取URI的信息
	 * @param request
	 */
	public static void getURIInfo(HttpServletRequest request)
	{
		request.getRequestURI();
		request.getRequestURL();
	}

}
